\documentclass[a4paper,12pt]{article}

\usepackage[margin=1.5cm]{geometry}
\usepackage{fancyvrb}

\title{New Discovery Regarding Function Arguments}
\author{Chen Rushan\\chenrsster@gmail.com}
\date{2009.08.17 20:51}

\setlength{\parskip}{1.2ex}
\setlength{\parindent}{0pt}

\begin{document}
\maketitle

Since function arguments are put on the stack, and the callee just fetch its
arguments from stack in order, not caring how the arguments are put, not knowing how
many arguments are exactly put on the stack, it's possible for the caller to cheat,
like passing only one argument to a function actually requiring two arguments, or
passing two arguments to a function requiring only one.

Now consider a program which consists of two files, named {\em file1.c} and {\em
file2.c}, and \verb=main= function reside in {\em file2.c}, as follows:

{\em file1.c}:
\begin{Verbatim}[frame=single]
void print(int i, int j)
{
        printf("%x %x\n", i, j);
}

void print2(long long ll)
{
        printf("%llx\n", ll);
}
\end{Verbatim}

{\em file2.c}:
\begin{Verbatim}[frame=single]
int main(int argc, char **argv)
{
        long long ll = 0x00FFEE00AA2345CC;

        print(ll);
        print2(0x11111, 0x2222);

        return 0;
}
\end{Verbatim}

You may even think this program can't be successfully built, but the truth is you
won't get any error messages, not even warning messages. As we mentioned above, the
callee doesn't care how you put the arguments, and how many arguments there are on
the stack, it just simply scan the stack in order, fetching the amount of bytes
needed, assigning to each argument of the function. Since integer of \verb=long long=
type is 8-byte long, twice as large in size as \verb=int=, it can also be treated as
two consecutive \verb=ints=, and this happens to be the case for the \verb=print(ll)=
call, which only supply one argument, but of 8-byte long, so it's treated by
\verb=print= as two arguments of type \verb=int=. For the 
\verb=print2(0x11111, 0x2222)= call, the situation is similar, but this time it's
two consecutive \verb=ints= being treated as one \verb=long long=, resulting in an 
argument of 0x222200011111. The output of this program is as follows:

\begin{Verbatim}[frame=single]
aa2345cc ffee00
222200011111
\end{Verbatim}

In fact, you can even call \verb=print= with one \verb=int= type argument, say 20,
it's OK too, and this 20 will become the first argument of \verb=print=, leaving the
second argument undefined, which results in an arbitrary output of \verb=printf=.

Now you may wonder if there's a way to prevent above things from happening, and let
the compiler issue errors when the number of arguments doesn't match the number of
formal parameters. The answer is yes, to force argument checking, simply add
declaration before you call the function, for the above example, modify {\em file2.c}
to be as follows:

\begin{Verbatim}[frame=single]
void print(int , int );
void print2(long long);

int main(int argc, char **argv)
{
        long long ll = 0x00FFEE00AA2345CC;

        print(ll);
        print2(0x11111, 0x2222);

        return 0;
}
\end{Verbatim}

Now if you recompile this program, you'll get errors complaining that the number of
arguments and parameters don't match, you need to modify your program to be like
this:

\begin{Verbatim}[frame=single]
void print(int , int );
void print2(long long);

int main(int argc, char **argv)
{
        long long ll = 0x00FFEE00AA2345CC;

        print(ll, 20);
        print2(0x11111);

        return 0;
}
\end{Verbatim}

Note also that this time \verb=ll= will be trimmed down to be an \verb=int= before
it's passed to \verb=print=, so it on longer occupies 8 bytes, only the last 4 bytes
will be put on the stack. The output of this program now is:

\begin{Verbatim}[frame=single]
aa2345cc 20
11111
\end{Verbatim}

But consider \verb=printf=, a function taking variable arguments, for such a
function, the argument checking is impossible no matter whether you provide the
declaration or not, so the following calls to \verb=printf= are always correct:

\begin{Verbatim}[frame=single]
printf("%d %d\n", 20);
printf("%x %x\n", (long long)0x00FFEE00AA2345CC);
printf("%d %d\n", 20, 30, 40);
\end{Verbatim}

You'll see output like this:

\begin{Verbatim}[frame=single]
20 -1079309048
aa2345cc ffee00
20 30
\end{Verbatim}

The second integer output by the first \verb=printf= call is just an arbitrary number
\verb=printf= finds right after 20 on the stack. Type conversion can actually be
omitted in the second \verb=printf=, since the argument itself is already larger than
an \verb=int=, but if the size of this argument is shorter than an \verb=int= then
the type conversion is necessary so that the argument will occupy the space used for
two \verb=ints=. For the last \verb=printf= call, 40 is simply omitted.

Now you may realize the importance of an include file, which normally used to provide
prototypes for a library. Without it, you may unconsciously call a function
incorrectly by giving it a mismatched number of arguments.

\end{document}

